
#include "QueueArray.h"

template <typename T>
QueueArray<T> :: QueueArray(int maxNumber = Queue<T>::MAX_QUEUE_SIZE)
{
   maxSize = maxNumber+ 1;
   front = 1;
   back = 0;
   dataItems = new T[maxSize];

}

template <typename T>
QueueArray<T> :: QueueArray(const QueueArray<T>& other)
{
   back = other.back;
   front = other.front;
   dataItems = new T[other.maxSize];
   maxSize = other.maxSize;
   for(int ix = front; ix != (back+1)% maxSize; ix = (ix+1)%maxSize)
   {
      dataItems[ix] = other.dataItems[ix];
   }
}

template <typename T>
QueueArray<T>& QueueArray<T> :: operator=(const QueueArray<T>& other)
{
   if (this == &other)
      return *this;
   delete[] dataItems;
   back = other.back;
   front = other.front;
   dataItems = new T[other.maxSize];
   maxSize = other.maxSize;
   for(int ix = front; ix != (back+1)% maxSize; ix = (ix+1)%maxSize)
   {
      dataItems[ix] = other.dataItems[ix];
   }
   return *this;
}

template <typename T>
QueueArray<T> :: ~QueueArray()
{
   delete[] dataItems;
}

template <typename T>
void QueueArray<T> :: enqueue(const T& newDataItem) throw (logic_error)
{
   if (isFull())
      throw logic_error("Queue is full");
   back = (back + 1) % maxSize;
   dataItems[back] = newDataItem;
}

template <typename T>
T QueueArray<T> :: dequeue() throw (logic_error)
{
   if (isEmpty())
      throw logic_error("Queue is empty");
   int returnIndex = front;
   front = (front + 1) % maxSize;
   return dataItems[returnIndex];
}

template <typename T>
void QueueArray<T> :: clear()
{
   back = 0;
   front = 1;
}

template <typename T>
bool QueueArray<T> :: isEmpty() const
{
   return (back + 1) % maxSize == front;
}

template <typename T>
bool QueueArray<T> :: isFull() const
{
   return (back + 2) % maxSize == front;
}

template <typename T>
void QueueArray<T> :: putFront(const T& newDataItem) throw (logic_error)
{
   if (isFull())
      throw logic_error("Queue is full");
   if (--front < 0)
      front = maxSize;
   dataItems[front] = newDataItem;
}

template <typename T>
T QueueArray<T> :: getRear() throw (logic_error)
{
   if (isEmpty())
      throw logic_error("Queue is empty");
   int returnIndex = back;
   if (--back < 0)
      back = maxSize;
   return dataItems[returnIndex];
}

template <typename T>
int QueueArray<T> :: getLength() const
{
   if (isEmpty())
      return 0;
   if (front <= back)
      return (back - front) + 1;
   return (back + 1) + (maxSize - front);
}

template <typename T>
void QueueArray<T>::showStructure() const 
// Array implementation. Outputs the data items in a queue. If the
// queue is empty, outputs "Empty queue". This operation is intended
// for testing and debugging purposes only.

{
    int j;   // Loop counter

    if ( isEmpty())
       cout << "Empty queue" << endl;
    else
    {
       cout << "Front = " << front << "  Back = " << back << endl;
       for ( j = 0 ; j < maxSize ; j++ )
           cout << j << "\t";
       cout << endl;
       if ( back >= front )
          for ( j = 0 ; j < maxSize ; j++ )
              if ( ( j >= front ) && ( j <= back ) )
                 cout << dataItems[j] << "\t";
              else
                 cout << " \t";
       else
          for ( j = 0 ; j < maxSize ; j++ )
              if ( ( j >= front ) || ( j <= back ) )
                 cout << dataItems[j] << "\t";
              else
                 cout << " \t";
       cout << endl;
    }
}

